package com.cmii.sjw.department.control.common;

import org.springframework.data.redis.core.RedisTemplate;

import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.TimeUnit;


/**
 * RedisService
 *
 * @author yinruidong
 * @date 2019/1/29
 * @description redis缓存操作service接口
 */
public interface RedisService {

	/**
	 * 通过key获取储存在redis中的value,并自动转换为给定类型的对象返回
	 * @param key
	 * @param clz value转换的类对象,redis存储为对象的json字符串
	 * @return
	 */
	<T> T get(final String key, final Class<T> clz);

	/**
	 * 通过key获取储存在redis中的value,并自动转换为给定类型的对象collection
	 * @param key
	 * @param clz
	 * @return
	 */
	<T> Collection<T> getCollection(final String key, final Class<T> clz);

	/**
	 * 向redis存入key和value, value将转换为json字符串(缓存不失效)
	 * @param key
	 * @param value
	 * @return
	 */
	<T> boolean set(String key, T value);


	/**
	 * 向redis存入key和value, value将转换为json字符串，并且设置存活时间
	 * @param key
	 * @param value
	 * @param liveTime 缓存有效时间
	 * @param timeUnit 时间颗粒度
	 * 	TimeUnit.DAYS          //天
	 *	TimeUnit.HOURS         //小时
	 *	TimeUnit.MINUTES       //分钟
	 *	TimeUnit.SECONDS       //秒
	 *	TimeUnit.MILLISECONDS  //毫秒
	 * @return
	 */
	<T> boolean set(final String key, final T value, final long liveTime,
			TimeUnit timeUnit);


	/**
	 * 向redis存入key和value, value将转换为json字符串，并且设置存活时间
	 * @param key
	 * @param value
	 * @param expireTime 缓存有效时间
	 * 	TimeUnit.DAYS          //天
	 *	TimeUnit.HOURS         //小时
	 *	TimeUnit.MINUTES       //分钟
	 *	TimeUnit.SECONDS       //秒
	 *	TimeUnit.MILLISECONDS  //毫秒
	 * @return
	 */
	<T> boolean set(final String key, final T value, LocalDateTime expireTime);


	/**
	 * 如果key不存在则向redis存入key和value并返回true,否则返回false
	 * @param key
	 * @param value
	 * @return
	 */
	<T> boolean setNx(final String key, final T value);

	/**
	 * 获取RedisTemplate
	 * @return
	 */
	RedisTemplate<String, String> getRedisTemplate();

	/**
	 * 设置键key的存活时间
	 * @param key
	 * @param timeUnit 时间颗粒度
	 * 	TimeUnit.DAYS          //天
	 *	TimeUnit.HOURS         //小时
	 *	TimeUnit.MINUTES       //分钟
	 *	TimeUnit.SECONDS       //秒
	 *	TimeUnit.MILLISECONDS  //毫秒
	 * @param time
	 * @return
	 */
	Boolean setTimeout(String key, TimeUnit timeUnit, final Long time);

	/**
	 * 将键存储为字符串值的整数值递增
	 * @param key
	 * @return
	 */
	long generate(String key);

	/**
	 * 检查key是否已经存在
	 *
	 * @param key
	 * @return
	 */
	boolean isExist(String key);

	/**
	 * 清空redis 所有数据
	 *
	 * @return
	 */
	String flushDb();

	/**
	 * 查看redis里有多少数据
	 * @return
	 */
	Long dbSize();

	/**
	 * 删除redis key
	 * @param key
	 * @return
	 */
	boolean delete(String key);

	/**
	 * 通过key向set集合中添加values元素数组
	 * @param key
	 * @param values
	 * @return
	 */
	<T> boolean sadd(String key, T... values);

	/**
	 * 通过key获取set中所的value
	 * @param key
	 * @param clz
	 * @return
	 */
	<T> Set<T> smembers(String key,final Class<T> clz);

	/**
	 * 通过key删除set中对应的value值
	 * @param key
	 * @param values
	 *            可以是一个对象 也可以是一个对象数组
	 * @return 删除的个数
	 */
	<T> Long srem(String key, T...values);

	/**
	 *  通过key向zset中添加value,score,其中score就是用来排序的
	 * @param key
	 * @param score
	 * @param member
	 * @return
	 */
	<T> boolean zadd(String key, double score,T member) ;

	/**
	 *通过key将获取score从start到end中zset的value
	 * socre从大到小排序
	 *当start为0 end为-1时返回全部
	 * @param key
	 * @param start
	 * @param end
	 * @param clz
	 * @return
	 */
	<T> Set<T> zrevrange(String key, long start, long end, Class<T> clz);

	/**
	 * 通过key获取zset中value的score值
	 * @param key
	 * @param value
	 * @return
	 */
	<T> Double zscore(String key, T value);

	/**
	 * 通过key删除在zset中指定的value
	 * @param key
	 * @param values
	 *            可以使一个对象 也可以是一个对象数组
	 * @return
	 */
	<T> Long zrem(String key, T...values);

	/**
	 * 通过key 和 field 获取指定的 value
	 * @param key
	 * @param field
	 * @param clz
	 * @return
	 */
	<T> T hget(final String key,final String field, final Class<T> clz);

	/**
	 * 通过key给field设置指定的值,如果key不存在,则先创建
	 * @param key
	 * @param field 字段
	 * @param value
	 * @return
	 */
	<T> boolean hset(String key, String field, T value) ;

	/**
	 * 通过key向list头部添加字符串
	 * @param key
	 * @param values 数组
	 *
	 * @return 返回list的value个数
	 */
	<T> boolean lpush(String key, T...values);

	/**
	 * 通过key从list尾部删除一个value,并返回该元素
	 * @param key
	 * @param clz
	 * @return
	 */
	<T> T rpop(String key, final Class<T> clz);

	/**
	 * 指定key的field是否存在
	 * @param key
	 * @param field 字段
	 * @return
	 */
	boolean hexists(String key, String field);

	/**
	 * 指定key的field
	 * @param key
	 * @param field
	 * @param delta
	 * @return
	 */
	boolean hincrby(String key, String field, Long delta);

	/**
	 * 获取hash表的字段数量
	 * @param key
	 * @return
	 */
	Long hlen(String key);

	/**
	 *获取剩余时间
	 * @param key
	 * @return
	 */
	Long getResidueTime(String key);

	/**
	 * 如果key不存在则向redis存入key和value并返回true,否则返回false
	 * 并且添加过期时间
	 * @param key
	 * @param value
	 * @return
	 */
	<T> boolean setNx(final String key, final T value,long time, TimeUnit timeUnit);

	/**
	 * 生成订单号
	 * @param bizPrefix 业务前缀
	 * @return 订单号
	 */
	String orderNoGenerator(String bizPrefix);

	/**
	 * 获取缓存数据
	 * @param key key
	 * @param clazz	value转换的类对象,redis存储为对象的json字符串
	 * @return T
	 */
	<T> T getCache(String key, Class<T> clazz);

	/**
	 * 设置缓存数据
	 * @param key key
	 * @param value value
	 * @param timeout 超时时间
	 */
	void setCache(String key, Object value, long timeout);
}
